"""
Classes necessary for handling the computer-player objects.
$Id: computerplayer.py,v 1.1 2004/12/17 09:57:49 krawczyk Exp $

Codes for Playermovement (stored in list_of_codes):
l, #    -- Number of frames to move left
r, #    -- right
s, #    -- collect snow for # frames
s2c, #  -- Set the amount of snow to collect!
m, #    -- go to the middle
o, #    -- go to the outside
M       -- add random modification!
"""

import pygame, copy, math, random
import config, game, player, snowball

class ComputerPlayer(player.Player):
    """
    A class for a computer enemy. Is derived of Player.
    """
    def __init__(self, configdict, gamedata):
        """
        Initialise a computerplayer.
        configdict -- configuration dictionary
        gamedata -- global gamedata
        needed_throwstrength -- Throw with this strength
        other_player -- the other player we are aiming at
        code -- code describing the actions of the player
        code_current -- index of current code
        frames_before_change -- number of frames, before next code is read. If <0 do it now!
        snow_2_collect -- how much snow should be collect before throwing
        """
        player.Player.__init__(self, configdict, gamedata)
        self.code = [
            ('s', 5),
            ('M',),
            ('s2c', 0),
            ('m', 5),
            ('s', 7)
            ]
        self.code_current = 0
        self.snow_2_collect = self.snow_max
        self.frames_before_change = -1
        self.needed_throwstrength = 0

    def Handle_Keys(self, key, keydown):
        """
        The Computerplayer ignores any kind of keys except '.'
        If '.' is pressed it prints itself
        """
        if key == pygame.K_PERIOD and keydown:
            for k,v in self.__dict__.iteritems():
                print k,'\t=\t',v
        return False

    def Update(self):
        if(not (self.action & 0xF000)):
            if self.Is_Throwing():
                if (self.strength >= self.needed_throwstrength):
                    self.strength = self._calculate_throwstrength(self.other_player[0])-self.gamedata.player_minstrength #self.needed_throwstrength
                    self.Throw(False)
            elif self.snow >= self.snow_2_collect:
                self.other_player = self._find_other_player()
                if self.other_player[0].Pos()[0]<self.Pos()[0]:
                    self.look = -1
                else:
                    self.look = 1
                self.needed_throwstrength = self._calculate_throwstrength(self.other_player[0]) - self.gamedata.player_minstrength
                self.Throw(True)
            elif self.frames_before_change < 0:
                while self.frames_before_change < 0:
                    code = self.code[self.code_current]
                    last = self.code[self.code_current-1]
                    if last[0] == 's':
                        self.Grab_snow(False)
                    if code[0] == 'l':
                        self.Set_Move(-1)
                        self.frames_before_change = code[1]
                    elif code[0] == 'r':
                        self.Set_Move(1)
                        self.frames_before_change = code[1]
                    elif code[0] == 's':
                        self.Grab_snow()
                        self.frames_before_change = code[1]
                    elif code[0] == 'm':
                        if self.Pos()[0] < config.scrsize[0]/2:
                            self.Set_Move(1)
                            self.frames_before_change = code[1]
                        else:
                            self.Set_Move(-1)
                            self.frames_before_change = code[1]
                    elif code[0] == 'o':
                        if self.Pos()[0] < config.scrsize[0]/2:
                            self.Set_Move(-1)
                            self.frames_before_change = code[1]
                        else:
                            self.Set_Move(1)
                            self.frames_before_change = code[1]
                    elif code[0] == 'M':
                        self._insert_new_code()
                        self._next_code()
                    elif code[0] == 's2c':
                        self.snow_2_collect = random.uniform(player.Player.snow_max, player.Player.snow_min_throw*player.Player.snow_max)
                        self._next_code()
                    else:
                        print "Unknown ComputerPlayer code:",code
                self._next_code()
            else:
                self.frames_before_change -= 1
            #elif self.snow < self.snow_max:
            #    self.Grab_snow()
            #else:
            #    self.other_player = self._find_other_player()
            #    if self.other_player[0].Pos()[0]<self.Pos()[0]:
            #        self.look = -1
            #    else:
            ##        self.look = 1
            #    self.needed_throwstrength = self._calculate_throwstrength(self.other_player[0]) - self.gamedata.player_minstrength
            #    self.Throw(True)
        player.Player.Update(self)

    def _calculate_throwstrength(self, otherplayer):
        """
        return the strength which is needed to hit otherplayer with a snowball
        """
        vx, vy = player.snowball_startvel
        vx = float(vx)
        vy = float(vy)
        dx = self.Pos()[0]-otherplayer.Pos()[0]
        if(dx < 0):
            vx *= -1
        try:
            p = math.sqrt((dx)/vx/(-vy)*(snowball.Snowball.gravity)/2)
        except:
            print dx, vx, vy
            p = 1
            raise
        return p
    
    def _find_other_player(self):
        """
        Return a tuple (player, playerindex) from the list of the players in self.gamedata who is not the player himself.
        playerindex is the index in the self.gamedata.players list.
        """
        plist = []
        index = 0
        for i in self.gamedata.players:
            if i != self:
                plist.append( (i, index) ) #Append player object and index
            index += 1
        return random.choice(plist)

    def _insert_new_code(self):
        c = random.choice(list_of_codes)
        if c == 's':
            t = random.randint(6,20)
        else:
            t = random.randint(5,12)
        self.code.append((c, t))
        
    def _next_code(self):
        self.code_current += 1
        if self.code_current >= len(self.code):
            self.code_current = 0

    def KKK():
        if(data.framecounter % 10 == 0): #Every 20 frames
            ppos = data.players[0].Pos()
            dx = ppos[0]-400
            snowball.Snowball(data.objs_pass, 1, (400,500), (vx*p, vy*p))

def Init():
    global list_of_codes
    print "Initialising computer enemy...",
    config.Status_top("Initialising AI...")
    list_of_codes=[ 's', 'l', 'r', 'm', 'o', 's', 's2c' ]
    print "Done!"
